#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <chrono>
#include <random>
#include <condition_variable>

// 函数原型声明
double run_single_thread_test(int thread_count, int compute_iter, int outer_iter);
double cpu_intensive_task(int iterations, int seed);
void thread_worker_iteration(int thread_id, int compute_iter, int outer_idx,
                            double* local_result, std::mutex* print_mutex);
void simulated_sync_operation(int thread_id, int seed, std::mutex* print_mutex);

// 全局随机数生成器
std::random_device global_rd;
std::mt19937_64 global_rng(global_rd());

// 主函数
int main(int argc, char**argv) {
    // 默认8个线程
    int thread_count = 8;
    int compute_iter = 100;
    int outer_iter = 10;  // 外部循环次数
    bool enable_single_thread = true;
    
    // 解析命令行参数
    if (argc > 1) thread_count = std::stoi(argv[1]);
    if (argc > 2) compute_iter = std::stoi(argv[2]);
    if (argc > 3) outer_iter = std::stoi(argv[3]);
    if (argc > 4) enable_single_thread = (std::stoi(argv[4]) != 0);
    
    std::cout << "===== 多线程CPU仿真器测试 =====" << std::endl;
    std::cout << "每次外循环创建的线程数量: " << thread_count << std::endl;
    std::cout << "每个线程计算循环次数: " << compute_iter << std::endl;
    std::cout << "外部循环次数: " << outer_iter << std::endl;
    std::cout << "线程工作函数仅执行计算，同步在主线程中处理" << std::endl;
    std::cout << "==============================" << std::endl;
    
    double single_thread_duration = 0.0;
    if (enable_single_thread) {
        std::cout << "开始单线程测试..." << std::endl;
        single_thread_duration = run_single_thread_test(thread_count, compute_iter, outer_iter);
        std::cout << "单线程总耗时: " << single_thread_duration << " 秒" << std::endl;
    }
    
    // 多线程测试 - 线程在外部循环内部创建
    std::cout << "开始多线程测试..." << std::endl;
    auto start_time = std::chrono::high_resolution_clock::now();
    
    // 外部循环 - 每次循环都创建新线程
    for (int outer_idx = 0; outer_idx < outer_iter; ++outer_idx) {
        if (outer_idx % 5 == 0) {  // 每5次循环输出一次进度
            std::cout << "执行外部循环 " << outer_idx + 1 << "/" << outer_iter << std::endl;
        }
        
        // 存储线程计算结果
        std::vector<double> thread_results(thread_count, 0.0);
        std::mutex print_mutex;  // 用于调试输出的互斥锁
        std::vector<std::thread> threads;
        
        // 在外部循环内部创建线程 - 仅执行计算任务
        for (int i = 0; i < thread_count; ++i) {
            threads.emplace_back(thread_worker_iteration, 
                               i, 
                               compute_iter, 
                               outer_idx,
                               &thread_results[i],
                               &print_mutex);
        }
        
        // 等待当前循环的所有线程完成计算（这是主要的同步点）
        for (auto& t : threads) {
            t.join();
        }
        
        // 所有线程计算完成后，在主线程中执行同步操作
        simulated_sync_operation(0, outer_idx * 10000, &print_mutex);
        
        // 汇总当前循环的结果
        double iteration_sum = 0.0;
        for (double res : thread_results) {
            iteration_sum += res;
        }
    }
    
    // 计算多线程总耗时
    auto end_time = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> multi_thread_duration = end_time - start_time;
    std::cout << "多线程总耗时: " << multi_thread_duration.count() << " 秒" << std::endl;
    
    // 计算加速比
    if (enable_single_thread) {
        double speedup = single_thread_duration / multi_thread_duration.count();
        std::cout << "加速比: " << speedup << std::endl;
    }
    
    // 输出结果汇总
    std::cout << "===== 结果汇总 =====" << std::endl;
    std::cout << "单线程耗时: " << single_thread_duration << std::endl;
    std::cout << "多线程耗时: " << multi_thread_duration.count() << std::endl;
    if (enable_single_thread) {
        std::cout << "加速比: " << (single_thread_duration / multi_thread_duration.count()) << std::endl;
    }
    
    return 0;
}

// 线程工作函数 - 仅执行计算任务，不包含任何同步操作
void thread_worker_iteration(int thread_id, int compute_iter, int outer_idx,
                            double* local_result, std::mutex* print_mutex) {
    // 仅执行计算任务，无同步操作
    *local_result = cpu_intensive_task(compute_iter, outer_idx * 1000 + thread_id);
    
    // 调试信息：仅输出计算完成通知，无同步逻辑
    #ifdef DEBUG
    std::lock_guard<std::mutex> lock(*print_mutex);
    std::cout << "线程 " << thread_id << " 完成计算任务" << std::endl;
    #endif
}

// 单线程测试实现 - 仅执行计算任务
double run_single_thread_test(int thread_count, int compute_iter, int outer_iter) {
    auto start_time = std::chrono::high_resolution_clock::now();
    
    // 单线程模拟：仅执行计算任务
    for (int outer_idx = 0; outer_idx < outer_iter; ++outer_idx) {
        for (int i = 0; i < thread_count; ++i) {
            // 仅执行计算任务
            double local_result = cpu_intensive_task(compute_iter, outer_idx * 1000 + i);
        }
    }
    
    auto end_time = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> total_time = end_time - start_time;
    return total_time.count();
}

// 模拟同步操作（在主线程中执行）
void simulated_sync_operation(int thread_id, int seed, std::mutex* print_mutex) {
    std::mt19937 rng(seed);
    
    // 准备阶段延迟（1-10ms）
    std::uniform_real_distribution<double> prepare_delay(0.001, 0.01);
    double prepare_time = prepare_delay(rng);
    std::this_thread::sleep_for(std::chrono::duration<double>(prepare_time));
    
    // 传输/确认阶段延迟（2-15ms）
    std::uniform_real_distribution<double> transfer_delay(0.002, 0.015);
    double transfer_time = transfer_delay(rng);
    
    // 主线程额外延迟
    if (thread_id == 0) {
        std::uniform_real_distribution<double> master_extra_delay(0.003, 0.02);
        transfer_time += master_extra_delay(rng);
    }
    
    std::this_thread::sleep_for(std::chrono::duration<double>(transfer_time));
    
    #ifdef DEBUG
    std::lock_guard<std::mutex> lock(*print_mutex);
    std::cout << "同步操作完成，耗时: " 
              << (prepare_time + transfer_time) * 1000 << "ms" << std::endl;
    #endif
}

// CPU密集型任务实现
double cpu_intensive_task(int iterations, int seed) {
    std::mt19937 rng(seed);
    std::uniform_real_distribution<double> dist(0.0001, 0.001);
    
    double result = 0.0;
    for (int i = 0; i < iterations; ++i) {
        result += std::sin(i * 0.001) * std::cos(i * 0.002);
        if (i % 10000 == 0) {
            std::this_thread::sleep_for(std::chrono::duration<double>(dist(rng)));
        }
    }
    return result;
}
    
